import java.io.*;

import javax.bluetooth.*;
import javax.microedition.io.*;
import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;

public final class BluetoothTest extends MIDlet implements CommandListener, Runnable {

	private final String SERVICE_NAME = "Bluetooth Test MIDlet";
	private final UUID SERVICE_UUID = new UUID("09876543210987654321ABCDEFFEDCBA", false);
	private final String SERVICE_URL;
	private final int SERVICE_ATTR_ID = 0x1234;
	// bluetooth variables
	private LocalDevice localDevice;
	private DiscoveryAgent discoveryAgent;
	// display variables
	private final List list;
	private final Command exit, send;
	private final Display display;
	// threading variables
	private Thread sendThread, receiveThread;
	private volatile boolean stop;

	//
	public BluetoothTest() {
		// initialize display variables
		display = Display.getDisplay(this);
		list = new List("Bluetooth Test MIDlet", List.IMPLICIT);
		exit = new Command("Exit", Command.EXIT, 1);
		send = new Command("Send", Command.OK, 2);
		list.addCommand(exit);
		list.addCommand(send);
		list.setCommandListener(this);
		display.setCurrent(list);
		// initialize URL variables
		SERVICE_URL = "btspp://localhost:" + SERVICE_UUID.toString() + ";name=" + SERVICE_NAME + ";authorize=false";
	}
	// MIDlet methods
	protected void destroyApp(boolean arg0) throws MIDletStateChangeException {}
	protected void pauseApp() {}
	protected void startApp() throws MIDletStateChangeException {
		try {
			localDevice = LocalDevice.getLocalDevice();
			localDevice.setDiscoverable(DiscoveryAgent.GIAC);
			discoveryAgent = localDevice.getDiscoveryAgent();
		} catch (BluetoothStateException blue) {
			System.err.print("Error ocurred: LocalDevice; DiscoveryAgent;");
			notifyDestroyed();
		}
		receiveThread = new Thread(this);
		receiveThread.start();
	}
	// CommandListener methods
	public void commandAction(Command c, Displayable d) {
		switch (c.getCommandType()) {
		case Command.EXIT:
			this.notifyDestroyed();
			break;
		case Command.OK:
			sendThread = new Thread(new Runnable() {
				public void run() {
					StreamConnection connection;
					DataOutputStream output;
					try {
						connection = (StreamConnection) Connector.open(discoveryAgent.selectService(SERVICE_UUID, ServiceRecord.NOAUTHENTICATE_NOENCRYPT, false));
						output = connection.openDataOutputStream();
						output.writeUTF(SERVICE_NAME);
						list.append(SERVICE_NAME, null);
						output.flush();
						output.close();
					} catch (BluetoothStateException e) {
						list.append("BluetoothStateException", null);
						return;
					} catch (IOException e) {
						list.append("IOException", null);
						return;
					}
				}
			});
			sendThread.start();
			break;
		}
	}
	
	public void run() {
		DataInputStream input;
		StreamConnection connection;
		StreamConnectionNotifier notifier = null;
		try {
			notifier = (StreamConnectionNotifier) Connector.open(SERVICE_URL);
			ServiceRecord record = localDevice.getRecord(notifier);
			record.setAttributeValue(SERVICE_ATTR_ID, new DataElement(DataElement.STRING, SERVICE_NAME));
		} catch (IOException e) {}
		while (!stop) {
			connection = null;
			try {
				connection = notifier.acceptAndOpen();
				if (connection != null) {
					input = connection.openDataInputStream();
					list.append(input.readUTF(), null);
					input.close();
					connection.close();
				}
			} catch (IOException e) { continue; }
		}
	}
}
